package com.mdp.tpa.wechat.client.wxpub.login.ctrl;

import java.util.*;

import com.mdp.core.entity.Result;
import com.mdp.core.entity.Tips;
import com.mdp.core.err.BizException;
import com.mdp.core.utils.ObjectTools;
import com.mdp.tpa.pub.client.SysClientService;
import com.mdp.tpa.pub.entity.SysUser;
import com.mdp.tpa.pub.entity.SysUserTpa;
import com.mdp.tpa.pub.entity.SysUserTpaInvite;
import com.mdp.tpa.pub.service.InviteCacheService;
import com.mdp.tpa.wechat.client.service.WechatMsgPushService;
import com.mdp.tpa.wechat.client.service.WxpubLoginHelpService;
import com.mdp.tpa.wechat.client.service.WxpubLoginService;
import com.mdp.tpa.wechat.config.AppProperties;
import com.mdp.tpa.wechat.config.WxopenProperties;
import com.mdp.tpa.wechat.config.WxpubProperties;
import com.mdp.tpa.wechat.entity.Oauth2AccessToken;
import com.mdp.safe.client.entity.CommonUserDetails;
import com.mdp.safe.client.entity.SafeAuthority;
import com.mdp.safe.client.entity.User;
import com.mdp.safe.client.utils.LoginUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;

@Controller
public class WxpubLoginController {

	@Autowired
	SysClientService sysClientService;

	@Autowired
	WxpubLoginService wxpubLoginService;

	@Autowired
	WxpubLoginHelpService wxpubLoginHelpService;

	String defaultRedirectUri="index";

	@Autowired
	InviteCacheService stateService;


	@Autowired
	WxpubProperties wxpubProperties;

	@Autowired
	WxopenProperties wxopenProperties;

	@Autowired
	WechatMsgPushService pushService;

	Logger logger = LoggerFactory.getLogger(WxpubLoginController.class);

	/**
	 * 微信网页扫码登陆、公众号授权登陆
	 * 登录一号店网站应用 https://passport.yhd.com/wechat/login.do 打开后，一号店会生成state参数，跳转到 https://open.weixin.qq.com/connect/qrconnect?appid=wxbdc5610cc59c1631&redirect_uri=https%3A%2F%2Fpassport.yhd.com%2Fwechat%2Fcallback.do&response_type=code&scope=snsapi_login&state=3d6be0a4035d839573b04816624a415e#wechat_redirect 微信用户使用微信扫描二维码并且确认登录后，PC端会跳转到 https://passport.yhd.com/wechat/callback.do?code=CODE&state=3d6be0a4035d839573b04816624a415e 为了满足网站更定制化的需求，我们还提供了第二种获取code的方式，支持网站将微信登录二维码内嵌到自己页面中，用户使用微信扫码授权后通过JS将code返回给网站。 JS微信登录主要用途：网站希望用户在网站内就能完成登录，无需跳转到微信域下登录后再返回，提升微信登录的流畅性与成功率。 网站内嵌二维码微信登录JS实现办法：
	 * 为了避免多次重定向刷新页面，这里采用第二种方式：前端页面获取code->后端通过code获取用户信息->再重定向到前端页面 的方案
	 * @param params
	 * @param request
	 * @return
	 */
	@GetMapping(value = "/login/token",params = "authType=wechat_wxpub")
	String wechatWxpubLogin(@RequestParam Map<String,Object> params ,HttpServletRequest request , RedirectAttributes attributes){
		String redirectUri= (String) params.get("redirectUri");
		if(!StringUtils.hasText(redirectUri)){//如果前端没有配置，默认回调当前页面
			redirectUri=defaultRedirectUri;
		}
		AppProperties appProperties=wxpubProperties;
		String code=(String)params.get("code");//该code由微信返回
		String state=(String)params.get("state");//该state前端上送微信，再由微信返回，一般为sessionid_5位随机数
		String appType=(String)params.get("appType");
		if("wxopen".equals(appType)){
			appProperties=wxopenProperties;
		}

		if(!stateService.valiInviteId(state)){
			return "redirect:"+redirectUri;
		}else {
			if(state.startsWith("login")){
				stateService.clearInviteId(state);
			}
		}
		if( !StringUtils.hasText(code)){//如果石第一次发起微信授权，
			return "redirect:"+redirectUri;
		}else if(StringUtils.hasText(code) && !StringUtils.hasText(state) ){
			return "redirect:"+redirectUri;
		}else if(StringUtils.hasText(code) && StringUtils.hasText(state) ){//微信端重定向回我方服务器，带code

			//用code换取openid
			//如果是token已经存在，不再向微信服务端申请
			try {
				Oauth2AccessToken token = wxpubLoginService.getOauth2AccessToken(appProperties, code);
				SysUser sysUser = null;
				//如果正确获取得到token，进行用户登录操作
				if (token != null && StringUtils.hasText(token.getOpenid())) {
					SysUserTpa tpa = new SysUserTpa();
					tpa.setAppid(appProperties.getAppid());
					tpa.setUnionid(token.getUnionid());
					tpa.setOpenid(token.getOpenid());
					tpa.setAppType(appType);
					SysUserTpa tpadb = sysClientService.getSysUserTpaByOpenid(token.getOpenid());
					//如果重未登陆过            或者登录过，但是scope位snsapi_userinfo下的tpa.unionid为空，帮助其补充unionid，建立关联关系
					if (tpadb == null) {
						if ("snsapi_userinfo".equals(token.getScope())) {
							Map<String, Object> userInfo = wxpubLoginService.getSnsUserInfoByOpenid(token);
							tpa = wxpubLoginHelpService.wechatUserInfoConvertToUserTpa(userInfo);
						}
						tpa.setStartdate(new Date());
						tpa.setUsername(tpa.getNickname());
						// 登记 userTpa到数据 注册user到数据库
						if (state.startsWith("login")) {
							sysUser = wxpubLoginHelpService.autoRegisterByUserTpa(state, tpa, false);
						} else if (state.startsWith("invite")) {
							sysUser = wxpubLoginHelpService.invite(state, tpa, false);
						} else if (state.startsWith("bind")) {
							sysUser = wxpubLoginHelpService.bind(state, tpa, false);
						} else if (state.startsWith("claim")) {
							sysUser = wxpubLoginHelpService.claim(state, tpa, false);
						}

					} else {
						tpa = tpadb;
						if (state.startsWith("login")) {
							sysUser = wxpubLoginHelpService.autoRegisterByUserTpa(state, tpa, true);
						} else if (state.startsWith("invite")) {
							sysUser = wxpubLoginHelpService.invite(state, tpa, true);
						} else if (state.startsWith("bind")) {
							sysUser = wxpubLoginHelpService.bind(state, tpa, true);
						} else if (state.startsWith("claim")) {
							sysUser = wxpubLoginHelpService.claim(state, tpa, true);
						}
					}
					Map<String, Object> result = wxpubLoginHelpService.loginByWechatWxpub(token.getOpenid(), code, sysUser != null ? sysUser.getUserid() : null, tpa.getPhoneno(), tpa.getUnionid());
					OAuth2AccessTokenResponse response = (OAuth2AccessTokenResponse) result.get("data");
					attributes.addAttribute("accessToken", response.getAccessToken().getTokenValue());
					User user = LoginUtils.getCurrentUserInfo();
					attributes.addAttribute("userid", user.getUserid());
					attributes.addAttribute("isOk", true);
					attributes.addAttribute("username", user.getUsername());
					if(ObjectTools.isNotEmpty(sysUser.getPassword()) && sysUser.getPassword().length()>=6){
						attributes.addAttribute("password", sysUser.getPassword());
						String context="您好，您在唛盟平台的登录账号为【"+sysUser.getDisplayUserid()+"】,登录密码为【"+sysUser.getPassword()+"】";
						pushService.pushTaskTplMsg(sysUser.getUserid(),"",context,"唛盟平台登录",sysUser.getUsername(),context);
					}
					attributes.addAttribute("inviteId", state);
					return "redirect:" + redirectUri;
				} else {
					User xuniUser = LoginUtils.createXuNiUser();
					Set<GrantedAuthority> as = new HashSet<>();
					SafeAuthority sa = new SafeAuthority("guest", "访客");
					as.add(sa);
					AnonymousAuthenticationToken authRequest = new AnonymousAuthenticationToken("guest", CommonUserDetails.fromUser(xuniUser), as);
					SecurityContext context = SecurityContextHolder.getContext();
					context.setAuthentication(authRequest);
					SecurityContextHolder.setContext(context);
					return "redirect:" + redirectUri;
				}
			}catch (BizException e){
				Tips tips=e.getTips();
				attributes.addAttribute("tipscode",tips.getTipscode());
				attributes.addAttribute("msg",tips.getMsg());
				attributes.addAttribute("isOk",false);
				attributes.addAttribute("inviteId",state);
				return "redirect:"+redirectUri;
			}catch (Exception e){
				attributes.addAttribute("tipscode","error");
				attributes.addAttribute("msg",e.getMessage());
				attributes.addAttribute("isOk",false);
				attributes.addAttribute("inviteId",state);
				return "redirect:"+redirectUri;
			}
		}
		return "redirect:"+redirectUri;
	}

	/**
	 * 个人账户登录，检查账户是否已创建，如未创建，自动创建主账户
	 * @return
	 */
	@PostMapping(value = "/login/wechat/wxpub/state")
	@ResponseBody  public Result createState(){
		 String state=stateService.createInviteId("login");
		SysUserTpaInvite invite=new SysUserTpaInvite();
		invite.setInviteId(state);
		stateService.setInvite(state,invite);
		return Result.ok().setData(state);
	}

}
